function ConvertAllFilesAndCleanUp(sDirectory,bCrop)
%%Convert .tif files to Imaris5 files using ConvertAllFiles.m
%First parameter is file path, second parameter is used to determine 
%whether images should be cropped to a region of interest.
%Directory will be searched recursively for *.tif files which will then be
%converted to the Imaris 5 file format. Only files containing the strings 
%' GFP' and ' mCherry' are considered.
%This function starts imaris automatically and does some cleaning process
%afterwards
%
% Hendrik Golzke and Patrik Rath
% Last change: 2010-08-16


    function DeleteAllTempFiles(sDirectory)
    %%Deletes all temporary directories in case there is no data loss

        %Get contents of dir
        lList=dir(sDirectory);

        for iFile=1:length(lList)
            %Don't go into . and ..
            if (isequal(lList(iFile).name,'.') || isequal(lList(iFile).name,'..'))
                continue;
            end;
            %Look for TempDir
            if (lList(iFile).isdir)
                if(~isequal([],regexp(lList(iFile).name,'^OurTempDirThatShouldBeEmpty\d{0,5}$')) )
                    lListSubDir=dir([sDirectory,'\',lList(iFile).name]);
                    %There should only be three files inside (.,.. and *.tif)
                    if (3==length(lListSubDir))
                        bDeleted=false;
                        for iFileAgain=3:length(lList)
                            %Check if file is already present in parent dir then
                            %delete TempDir
                            if (isequal(lList(iFileAgain).name,lListSubDir(3).name) && lList(iFileAgain).bytes==lListSubDir(3).bytes)
                                try
                                    rmdir([sDirectory '\' lList(iFile).name],'s');
                                catch
                                    disp(['Probably Imaris is blocking a folder, couldn''t delete ' sDirectory '\' lList(iFile).name]);
                                end;
                                bDeleted=true;
                                break;
                            end;
                        end;
                        if (false == bDeleted)
                            disp(['Didn''t delete dir, file not present in parent directory: ' sDirectory '\' lList(iFile).name '\' lListSubDir(3).name]);
                        end;
                    elseif (2==length(lListSubDir))
                        try
                            rmdir([sDirectory '\' lList(iFile).name],'s');
                        catch
                            disp(['Probably Imaris is blocking a folder, couldn''t delete ' sDirectory '\' lList(iFile).name]);
                        end;
                    else
                        disp(['Didn''t delete dir, too many files in temporary directory: ' sDirectory '\' lList(iFile).name]);
                    end;
                else
                    DeleteAllTempFiles([sDirectory '\' lList(iFile).name]);
                end;
            end;
        end;
    end



    function ConvertAllFiles(sDirectory,apImaris,bCrop)
    %%Convert .tif files to Imaris5 files
    %ConvertAllFiles(sDirectory,apImaris,bCrop);
    %Expects a Directory as string and an instance of Imaris and a boolean as 
    %parameters. Last parameter is used to determine whether images should be 
    %cropped to a region of interest.
    %Directory will be searched recursively for *.tif files which will then be
    %converted to the Imaris 5 file format. Only files containing the strings 
    %' GFP' and ' mCherry' are considered.
    %
    % Hendrik Golzke and Patrik Rath
    % Last change: 2010-08-24
        sVersionString = '100824';

        lList=dir(sDirectory);
        for iFile=1:length(lList)
            %Don't go into . and ..
            if (isequal(lList(iFile).name,'.') || isequal(lList(iFile).name,'..'))
                continue;
            end;
            %Go into sub folders
            if (lList(iFile).isdir)
                sTempDir2=[sDirectory '\' lList(iFile).name];
                ConvertAllFiles(sTempDir2,apImaris,bCrop);
                continue;
            end;
            sFilename=lList(iFile).name;
            if ( ~isequal([],strfind(sFilename,' mCherry')) || ~isequal([],strfind(sFilename,' GFP')) )
                ext = sFilename(end-3:end);
                if(strcmpi(ext,'.tif'))
                    %Open File in a temprorary directory since Imaris always
                    %tries to open all the tiff files as a z stack
                    sTempBaseDir='OurTempDirThatShouldBeEmpty';
                    %Try to create a new TempDir and try not to create an
                    %endless loop
                    for iTry=1:100
                        sTempDir=[sTempBaseDir num2str(randi(99999))];
                        [~,test,~] = mkdir(sDirectory,sTempDir);
                        if (isequal(test,''))
                            break;
                        end;
                    end;

                    %Better check if the directory is really empty
                    if ( 2<length(dir([sDirectory '\' sTempDir])) )
                        disp(['Temporary directory not empty! Aborted conversion in folder ' sDirectory]);
                        break;
                    end;

                    sFile=[sDirectory '\' sFilename];
                    sTempFile=[sDirectory '\' sTempDir '\' sFilename];
                    %matlabs movefile is slower than calling move since it
                    %actually copies the files
                    movefile(sFile,sTempFile);
                    %Try to open file, if not display error
                    try
                        apImaris.FileOpen(sTempFile);
                    catch struError
                        disp(['Imaris ' struError.message]);
                    end;

                    %Test whether we opened the file
                    if ( ~isequal(apImaris.GetCurrentFileName,sTempFile) )
                        disp(['Can''t open file: ' sTempFile]);
                    else
                        %Load Data (Channels)
                        dsChannels = apImaris.mDataSet;
                        %Get data like dimensions &c.
                        struChannels = dsChannels.get;

                        %Set the voxel size to 0.178*0.178*0.2 um^3
                        dsChannels.mExtendMaxX = 0.178 * dsChannels.mSizeX;
                        dsChannels.mExtendMaxY = 0.178 * dsChannels.mSizeY;
                        dsChannels.mExtendMaxZ = 0.200 * dsChannels.mSizeZ;
                        dsChannels.mUnit = 'um';

                        %Set the channel name and colour
                        if (~isequal([],strfind(sFilename,' mCherry')))
                            dsChannels.SetChannelName(0,'mCherry');
                            dsChannels.SetChannelColor(0,1,0,0,0);
                        elseif (~isequal([],strfind(sFilename,' GFP')))
                            dsChannels.SetChannelName(0,'GFP');
                            dsChannels.SetChannelColor(0,0,1,0,0);
                        end;

                        %Set last slice to zero of first channel (just in case
                        %there is an error)
                        %Set last slice to zero
                        for iChannel=0:(struChannels.mSizeC-1)
                            dsChannels.SetDataSlice(uint16(zeros(struChannels.mSizeX,struChannels.mSizeY)),struChannels.mExtendMaxZ-1, iChannel, 0);
                        end;


                        if (true==bCrop)
                            %Do a crop to region of interest
                            iStartX=int16((struChannels.mSizeX-450)/2);
                            iStartY=int16((struChannels.mSizeY-450)/2);
                            dsChannels.Crop(iStartX,450,iStartY,450,0,struChannels.mSizeZ,0,struChannels.mSizeC,0,struChannels.mSizeT);
                        end;

                        %We want to put the date into subdirs, if there is
                        %something to stitch (lots of files present)
                        sSubDir='';
                        %At least two tif files present?
                        bToStitch = (1<length(dir([sDirectory '\*.nd'])));
                        if (bToStitch && ~isequal([],strfind(sFilename,' mCherry')))
                            [~,~,~]=mkdir(sDirectory,'mCherry to stitch');
                            sSubDir='mCherry to stitch\';
                        elseif (bToStitch && ~isequal([],strfind(sFilename,' GFP')))
                            [~,~,~]=mkdir(sDirectory,'GFP to stitch');
                            sSubDir='GFP to stitch\';
                        end;

                        %Set channel colour range to standard for channel 0
                        dsChannels.SetChannelRange(0,0,65023)

                        %Center view
                        apImaris.mSurpassCamera.Fit;

                        %Replace 6 with 06 in Filename &c.
                        [viStart,~,~,cellRegExp]=regexp(sFilename,'\d_w\dConfocal');
                        if ( length(viStart)==1 && isequal([],regexp(sFilename,'\d{2}_w\dConfocal')) )
                            sRegExp=cellRegExp{1,1};
                            sRegExp = ['0' sRegExp(1) '_w' sRegExp(4) 'Confocal'];
                            sFilename = regexprep(sFilename,'\d_w\dConfocal',sRegExp);
                        else
                            %Replace no number with 00 in file name
                            [viStart,~,~,cellRegExp]=regexp(sFilename,'[A-Za-z]_w\dConfocal');
                            if (length(viStart)==1)
                                sRegExp=cellRegExp{1,1};
                                sRegExp = [sRegExp(1) '00' '_w' sRegExp(4) 'Confocal'];
                                sFilename = regexprep(sFilename,'[A-Za-z]_w\dConfocal',sRegExp);
                            end;
                        end;

                        %Save data
                        sImarisFile = [ sSubDir sFilename(1:end-4) ' tif_to_ims' sVersionString '.ims'];
                        apImaris.FileSave([sDirectory '\' sImarisFile ],'writer="Imaris5"');
                    end;

                    %try to move file back, if it doesn't work, just copy it
                    try
                        %Calling move is faster than movefile since matlab
                        %is atually copying the files
                        movefile(sTempFile,sFile);
                    catch
                        %Error message supressed since there is now a script
                        %for cleaning up
                        %['Imaris seems to be blocking file ' sTempFile];
                        copyfile(sTempFile,sFile,'f');
                    end;

                    %This won't work, because Imaris is blocking the directory
                    %rmdir([sDirectory '\' sTempDir])
                end;
            end;

            %Check whether there are multiple channels
            if (~isequal([],strfind(sFilename,' mCherry')) && exist('sImarisFile','var'))
                sGfpFile = strrep(sImarisFile,'_w3Confocal mCherry','_w2Confocal GFP');
                sGfpFile = strrep(sGfpFile,'_w2Confocal mCherry','_w1Confocal GFP');
                sGfpFile = strrep(sGfpFile,'mCherry to stitch\','GFP to stitch\');
                %Does a GFP file exists?
                if (0~=exist([sDirectory '\' sGfpFile],'file'))
                    dsMcherry = apImaris.mDataSet.Clone;
                    try
                        apImaris.FileOpen([sDirectory '\' sGfpFile])
                    catch struError
                        disp(['Imaris ' struError.message]);
                        disp(['Couldn''t open file: ' sDirectory '\' sGfpFile]);
                        break;
                    end;
                    dsGfp=apImaris.mDataSet;
                    %Which dataset has the greater z-stack? Sometimes there is
                    %an error, where Imaris creates 2 extra slices ...
                    iSmallerZ=dsGfp.mSizeZ;
                    bSliceDifference=false;
                    if (abs(iSmallerZ-dsMcherry.mSizeZ)>2)
                        bSliceDifference  = true;
                    end
                    if (iSmallerZ > dsMcherry.mSizeZ)
                        iSmallerZ = dsMcherry.mSizeZ;
                    end;
                    %Make new Channel in other dataset and name it &c.
                    dsMcherry.Resize(0,dsMcherry.mSizeX,0,dsMcherry.mSizeY,0,iSmallerZ,0,dsMcherry.mSizeC+1,0,dsMcherry.mSizeT);
                    dsMcherry.SetChannelColor(dsMcherry.mSizeC-1,0,1,0,0);
                    dsMcherry.SetChannelName(dsMcherry.mSizeC-1,'GFP');
                    dsMcherry.SetChannelRange(dsMcherry.mSizeC-1,0,65023);
                    %Copy channels
                    for iZSlice=0:iSmallerZ-1
                        dsMcherry.SetDataSlice(dsGfp.GetDataSlice(iZSlice,0,0),iZSlice,dsMcherry.mSizeC-1,0);
                    end;
                    %Set new dataset
                    apImaris.mDataSet = dsMcherry;
                    %free RAM
                    clear dsGfp;
                    %Save file
                    sSubDir='';
                    if (bToStitch)
                        [~,~,~]=mkdir(sDirectory,'2channels to stitch');
                        sSubDir='2channels to stitch\';
                    end;
                    %Build filename
                    s2ChannelFile=sFilename(1:end-4);
                    s2ChannelFile=strrep(s2ChannelFile,' mCherry',' ');
                    s2ChannelFile=[sDirectory '\' sSubDir  s2ChannelFile '2channels' sVersionString '.ims'];
                    if (bSliceDifference)
                        disp(['More than two z slices difference in GFP and mCherry in original data of file ' s2ChannelFile]);
                    end
                    apImaris.FileSave(s2ChannelFile,'writer="Imaris5"');
                end;
            end;
            %Clear sImarisFile because it is used to determine if the we use
            %an ims for adding a channel
            clear sImarisFile;
        end;
    end



    %Check whether the user supplied sDirectory
    if (~exist('sDirectory','var'))
        sDirectory = uigetdir('C:\','Choose a directory to convert from tiff to ims');
        if isequal(sDirectory,0)
            return;
        end;
    end;
    if ~isdir(sDirectory)
        return;
    end;
    %Check whether user supplied bCrop if not the standard is true
    if (~exist('bCrop','var'))
        bCrop = true;
    end;
    apImaris = actxserver('Imaris.Application');
    ConvertAllFiles(sDirectory,apImaris,bCrop);
    %Better clear apImaris than using apImaris.quit, because that is not
    %always working
    clear apImaris;
    %We better wait 10 seconds so that windows notices that Imaris is not
    %active anymore and removes all the folder locks
    pause(10);
    DeleteAllTempFiles(sDirectory);
end